# Go运算符优先级:容易踩坑的5个案例
Go语言中的运算符优先级虽然与其他语言相似,但仍有一些容易被忽视的细节。本文将通过5个实际案例,带你深入理解Go运算符优先级,避免常见错误。
## 案例1:算术运算符与比较运算符的优先级混淆
```go
result := 5 + 3 * 2 > 10
fmt.Println(result) // 输出什么?
```
很多开发者会认为结果是`true`,但实际上输出是`false`。这是因为:
1. 乘法`*`的优先级高于加法`+`,所以先计算`3 * 2 = 6`
2. 然后计算`5 + 6 = 11`
3. 最后比较`11 > 10`,确实为`true`
然而,原代码中的`>`优先级其实低于算术运算,所以表达式被正确计算。这个问题在于开发者对运算顺序的直觉判断。
## 案例2:位运算符与逻辑运算符的优先级陷阱
```go
a, b, c := 1, 2, 3
if a | b == c {
fmt.Println("条件成立")
} else {
fmt.Println("条件不成立")
}
```
这段代码会输出"条件不成立",因为:
1. `==`的优先级高于`|`,所以先计算`b == c`得到`false`(0)
2. 然后计算`a | 0`,结果为`1`
3. 在if条件中,非零值被视为`true`
正确的写法应该是:`if (a | b) == c`
## 案例3:指针解引用与字段访问的优先级
```go
type Person struct {
name string
age int
}
p := &Person{"Alice", 30}
fmt.Println(*p.age) // 编译错误
```
这里会出现编译错误,因为:
1. `.`(字段访问)的优先级高于`*`(解引用)
2. Go会先尝试访问`p.age`,但`p`是指针,不能直接访问字段
正确写法应该是:`(*p).age`,或者更简洁的Go特有写法:`p.age`
## 案例4:混合赋值运算符的优先级问题
```go
a := 1
b := 2
a *= b + 1
fmt.Println(a) // 输出什么?
```
结果是`3`而不是`4`,因为:
1. `+`的优先级高于`*=`
2. 所以先计算`b + 1 = 3`
3. 然后计算`a *= 3`,即`a = a * 3 = 1 * 3 = 3`
如果想先执行`a *= b`再加1,应该写成:`a = a*b + 1`
## 案例5:通道操作与逻辑运算的优先级
```go
ch := make(chan int, 1)
ch <- 1
select {
case <-ch != 0:
fmt.Println("收到非零值")
default:
fmt.Println("默认情况")
}
```
这段代码会导致编译错误,因为:
1. `!=`的优先级高于`<-`
2. Go会先尝试比较`ch != 0`,这是非法操作
正确写法应该是:`case (<-ch) != 0:`
## 总结表格:Go运算符优先级(从高到低)
| 优先级 | 运算符 |
|--------|--------|
| 5 | `*` `/` `%` `<<` `>>` `&` `&^` |
| 4 | `+` `-` `|` `^` |
| 3 | `==` `!=` `<` `<=` `>` `>=` |
| 2 | `&&` |
| 1 | `||` |
记住这些优先级规则,可以避免许多常见错误。当不确定时,使用括号明确表达你的意图是最安全的做法。
在实际开发中,建议:
1. 对于复杂表达式,合理使用括号
2. 将复杂表达式拆分为多个简单表达式
3. 编写单元测试验证表达式行为
4. 团队统一代码风格,避免歧义
希望这些案例能帮助你在Go开发中更准确地使用运算符,写出更可靠的代码。